home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mush-7.1.1 / hdr_sw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-02  |  11.3 KB  |  399 lines

  1. /* @(#)hdr_sw.c    (c) copyright    2/17/90 (Dan Heller) */
  2.  
  3. /* This file handles all the header subwindow code.  It would be much
  4.  * better if this subwindow, which displays the headers for the current
  5.  * folder, were a textsw.  That way, this file would go away completely.
  6.  * Until then, we have to create the window (canvas), define an event
  7.  * handler for when events happen in this window, create our own scrollbar,
  8.  * figure out when the user scrolls with it, attach our own popup menu to
  9.  * the canvas, handle events for that, let's see... kitchen sink?  Oh,
  10.  * that's over there in the corner.
  11.  */
  12. #include "mush.h"
  13. #ifdef SUN_4_0 /* SunOS 4.0+ */
  14. #include <sunwindow/win_keymap.h>
  15. #endif /* SUN_4_0 */
  16.  
  17. extern Panel hdr_panel;
  18. extern void hdr_io(), fkey_interposer();
  19.  
  20. static Notify_value scroll_hdr();
  21. static void msg_menu_func(), do_menu(), msg_menu_notify();
  22. static Menu msg_menu;
  23. static Menu_item cur_msg_item;
  24.  
  25. void
  26. make_hdr_sw(parent)
  27. Frame parent;
  28. {
  29.     Textsw tmpsw;
  30.  
  31.     if (!(hdr_sw = window_create(parent, CANVAS,
  32.     WIN_HEIGHT,        10 + screen*l_height(),
  33.     WIN_WIDTH,        WIN_EXTEND_TO_EDGE,
  34.     WIN_BELOW,        hdr_panel,
  35.     WIN_EVENT_PROC,        hdr_io,
  36.     CANVAS_AUTO_CLEAR,    TRUE,
  37.     CANVAS_RETAINED,    TRUE,
  38.     WIN_CONSUME_KBD_EVENTS,
  39.         WIN_ASCII_EVENTS, WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS, NULL,
  40.     WIN_IGNORE_KBD_EVENTS,
  41.         WIN_UP_ASCII_EVENTS, NULL,
  42.     WIN_CONSUME_PICK_EVENTS,
  43.         LOC_WINENTER, WIN_MOUSE_BUTTONS, LOC_MOVE, NULL,
  44.     WIN_VERTICAL_SCROLLBAR, scrollbar_create(0),
  45.     NULL)))
  46.     perror("hdr_sw"), cleanup(0);
  47.     hdr_win = canvas_pixwin(hdr_sw);
  48.     (void) notify_interpose_event_func(hdr_sw, fkey_interposer, NOTIFY_SAFE);
  49.     (void) notify_interpose_event_func(hdr_sw, scroll_hdr, NOTIFY_SAFE);
  50.     scrollbar_set((Scrollbar)window_get(hdr_sw, WIN_VERTICAL_SCROLLBAR),
  51.     SCROLL_NORMALIZE,    FALSE,
  52.     SCROLL_ADVANCED_MODE,    TRUE,
  53.     SCROLL_LINE_HEIGHT,    l_height(),
  54.     SCROLL_VIEW_LENGTH,    screen,
  55.     NULL);
  56. #ifdef SUN_4_0 /* SunOS 4.0+ */
  57.     /* This is a particularly ugly hack.  If Sun only documented the correct
  58.      * way to set up the key mapping for a window the way that textsw's do
  59.      * then we wouldn't have to do anything this awful.  Maybe in 4.2.....
  60.      *
  61.      * The object here is to get the same translation table for our header
  62.      * canvas as for a textsw (more or less anyway).  This way the arrow
  63.      * keys and such work right.
  64.      */
  65.     tmpsw = window_create(parent, TEXTSW, NULL);
  66. #ifdef SUN_4_1
  67.     keymap_from_fd[(int)window_get(hdr_sw, WIN_FD)].keymap =
  68.     keymap_from_fd[(int)window_get(tmpsw, WIN_FD)].keymap;
  69.     keymap_from_fd[(int)window_get(tmpsw, WIN_FD)].keymap = (Keymap *) 0;
  70. #else /* !SUN_4_1 */
  71.     keymap_from_fd[(int)window_get(hdr_sw, WIN_FD)].kf_keymap =
  72.     keymap_from_fd[(int)window_get(tmpsw, WIN_FD)].kf_keymap;
  73.     keymap_from_fd[(int)window_get(tmpsw, WIN_FD)].kf_keymap = (Keymap *) 0;
  74. #endif /* SUN_4_1 */
  75.     (void) window_destroy(tmpsw);
  76. #endif /* SUN_4_0 */
  77. }
  78.  
  79. static Notify_value
  80. scroll_hdr(canvas, event, arg, type)
  81. Canvas    canvas;
  82. Event    *event;
  83. Notify_arg    arg;
  84. Notify_event_type    type;
  85. {
  86.     int amount, count, i;
  87.     int show_deleted = !!do_set(set_options, "show_deleted");
  88.     char *argv[3], msgnum[8];
  89.     Scrollbar sb;
  90.     argv[0] = "headers";
  91.     argv[1] = msgnum;
  92.     argv[2] = NULL;
  93.  
  94.     switch (decode_scroll((Notify_client) canvas, event, screen, &amount)) {
  95.     case MUSH_SCROLL_PASS_EVENT:
  96.         switch(ID) {
  97.         case SCROLL_ENTER:
  98.         case SCROLL_EXIT:
  99.             return NOTIFY_IGNORED;
  100.         case SCROLL_REQUEST:
  101.             sb = (Scrollbar)arg;
  102.             switch( (Scroll_motion)
  103.              scrollbar_get(sb, SCROLL_REQUEST_MOTION)) {
  104.             case SCROLL_LINE_FORWARD:
  105.                 amount = 1;
  106.                 break;
  107.             case SCROLL_LINE_BACKWARD:
  108.                 amount = -1;
  109.                 break;
  110.             case SCROLL_ABSOLUTE:
  111.                 i = (int)scrollbar_get(sb, SCROLL_VIEW_START);
  112.                 if (!show_deleted) {
  113.                 count = i;
  114.                 for (i = 0; i < msg_cnt-1; i++)
  115.                         if (!ison(msg[i].m_flags, DELETE) &&
  116.                         count-- == 0)
  117.                     break;
  118.                 }
  119.                 (void) sprintf(msgnum, "%d", i+1);
  120.                 argv[1] = msgnum;
  121.                 (void) do_hdrs(2, argv, NULL);
  122.                 return(NOTIFY_DONE);
  123.             default:
  124.                 amount =
  125.                 (int)scrollbar_get(sb, SCROLL_VIEW_START) -
  126.                 (int)scrollbar_get(sb, SCROLL_LAST_VIEW_START);
  127.                 break;
  128.             }
  129.             break;
  130.         default:
  131.             return notify_next_event_func(canvas, event, arg, type);
  132.         }
  133.         break;
  134.     case MUSH_SCROLL_IGNORE:
  135.         return NOTIFY_IGNORED;
  136.     case MUSH_SCROLL_TO:
  137.         if (amount == 1) {
  138.         argv[1] = "1";
  139.         (void) do_hdrs(2, argv, NULL);
  140.         return NOTIFY_DONE;
  141.         } else {
  142.         (void) sprintf(msgnum, "%d", msg_cnt - screen + 1);
  143.         argv[1] = msgnum;
  144.         (void) do_hdrs(2, argv, NULL);
  145.         return NOTIFY_DONE;
  146.         }
  147.     }
  148.     if (amount == screen)
  149.     argv[1] = "+";
  150.     else if (amount == -screen)
  151.     argv[1] = "-";
  152.     else if (amount >= 0) {
  153.     if (amount < screen)
  154.         (void) sprintf(msgnum, "%d", min(n_array[amount]+1, msg_cnt-1));
  155.     else {
  156.         /* so much for layering */
  157.         for (i = n_array[0]+1; i < msg_cnt-1 && amount > 0; i++)
  158.         if (show_deleted || !ison(msg[i].m_flags, DELETE))
  159.             amount--;
  160.         (void) sprintf(msgnum, "%d", i);
  161.     }
  162.     } else {
  163.     /* so much for layering */
  164.     for (i = n_array[0]; i > 0 && amount < 0; i--)
  165.         if (show_deleted || !ison(msg[i-1].m_flags, DELETE))
  166.         amount++;
  167.     (void) sprintf(msgnum, "%d", i + 1);
  168.     }
  169.     (void) do_hdrs(2, argv, NULL);
  170.     return NOTIFY_DONE;
  171. }
  172.  
  173. /*
  174.  * Routines to handle io on the hdr_sw (canvas).
  175.  */
  176.  
  177. /* if MENU button goes down on a hdr, drawbox around hdr and popup menu */
  178. #define draw(x1,y1,x2,y2) (void) pw_vector(hdr_win, x1,y1,x2,y2,PIX_XOR,1)
  179. #define box(x1,y1,x2,y2)  \
  180.     draw(x1,y1, x1,y2), draw(x1,y2, x2,y2), \
  181.     draw(x2,y2, x2,y1), draw(x2,y1, x1,y1)
  182.  
  183. #define READ_MSG    (char *)'r'
  184. #define DEL_MSG        (char *)'d'
  185. #define UNDEL_MSG    (char *)'u'
  186. #define REPL_MSG    (char *)'R'
  187. #define SAVE_MSG    (char *)'s'
  188. #define PRNT_MSG    (char *)'p'
  189. #define PRE_MSG        (char *)'P'
  190. #define HELP_MSG    (char *)'H'
  191.  
  192. /*ARGSUSED*/
  193. void
  194. hdr_io(canvas, event, arg)
  195. Canvas canvas;
  196. Event *event;
  197. caddr_t arg;
  198. {
  199.     static int    which_cursor;
  200.     int     line;
  201.  
  202.     if (ID == WIN_REPAINT) {
  203.     if (is_iconic != (int) window_get(tool, FRAME_CLOSED)) {
  204.         check_new_mail();
  205.  
  206.         /*  Reload time with value of timeout upon timer expiration. */
  207.         mail_timer.it_interval.tv_sec = time_out;
  208.  
  209.         mail_timer.it_value.tv_sec = time_out;
  210.         (void) notify_set_itimer_func(tool, do_check,
  211.         ITIMER_REAL, &mail_timer, (struct itimerval *) 0);
  212.         is_iconic = 0;
  213.     }
  214.     }
  215.  
  216.     /* make cursor change which button is lit */
  217.     switch (which_cursor) {
  218.     case 0 : (void) window_set(canvas, WIN_CURSOR, l_cursor, NULL);
  219.     when 1 : (void) window_set(canvas, WIN_CURSOR, m_cursor, NULL);
  220.     when 2 : (void) window_set(canvas, WIN_CURSOR, r_cursor, NULL);
  221.     }
  222.  
  223.     which_cursor = (which_cursor+1) % 3;
  224.  
  225.     /* just return -- we just wanted to make the cursor flicker */
  226.     if (ID == LOC_STILL || ID == LOC_MOVE || ID == LOC_WINENTER ||
  227.     ID == LOC_RGNENTER || ID == KBD_USE || ID == KBD_DONE)
  228.     return;
  229.  
  230.     if (event_is_button(event) && event_is_down(event)) {
  231.     line = (event_y(event) - 5) / l_height();
  232.     if (line < 0)
  233.         line = 0;
  234.     else if (line >= screen)
  235.         line = screen - 1;
  236.     if (!msg_cnt || n_array[line] > msg_cnt)
  237.         return;
  238.     if (ID == MS_RIGHT)
  239.         do_menu(hdr_sw, event, window_get(hdr_sw, WIN_FD), n_array[line]);
  240.     else if (ID == MS_MIDDLE) {
  241.         set_isread(n_array[line]);
  242.         msg_menu_func(DEL_MSG, n_array[line]);
  243.     } else {
  244.         int do_do_hdrs = 0;
  245.         if (current_msg != n_array[line]) {
  246.         current_msg = n_array[line];
  247.         do_do_hdrs++;
  248.         }
  249.         if (ison(msg[current_msg].m_flags, UNREAD))
  250.         do_do_hdrs++;
  251.         (void) display_msg(n_array[line], (u_long)0);
  252.         if (do_do_hdrs)
  253.         (void) do_hdrs(0, DUBL_NULL, NULL);
  254.     }
  255.     } else
  256.     window_default_event_proc(canvas, event, NULL);
  257. }
  258.  
  259. static struct menu_rec {
  260.     char *str;    /* Menu item label. */
  261.     char *data;    /* Menu item client data. */
  262. };
  263.  
  264. static void
  265. get_msg_menu()
  266. {
  267.     int i;
  268.     Menu_item mi = NULL;
  269.  
  270.     static struct menu_rec msg_items[] = {
  271.     { "Read",            READ_MSG  },
  272.     { "Delete",          DEL_MSG   },
  273.     { "Undelete",        UNDEL_MSG },
  274.     { "Reply",           REPL_MSG  },
  275.     { "Save",            SAVE_MSG  },
  276.     { "Preserve",        PRE_MSG   },
  277.     { "Print",           PRNT_MSG  },
  278.     { "Help",            HELP_MSG  },
  279.     };
  280.  
  281.     msg_menu = menu_create(MENU_NOTIFY_PROC, msg_menu_notify, NULL);
  282.     for (i = 0; i < ArraySize(msg_items); i++) {
  283.     mi = menu_create_item(MENU_STRING,    msg_items[i].str,
  284.                   MENU_CLIENT_DATA,    msg_items[i].data,
  285.                   NULL);
  286.     (void) menu_set(msg_menu, MENU_APPEND_ITEM, mi, NULL);
  287.     }
  288. }
  289.  
  290. static void
  291. msg_menu_notify(menu, item)
  292. Menu menu;
  293. Menu_item item;
  294. {
  295.     cur_msg_item = item;
  296. }
  297.  
  298. static void
  299. do_menu(can_sw, event, fd, message)
  300. Canvas can_sw;
  301. Event *event;
  302. int fd, message;
  303. {
  304.     char *action;
  305.     static char buf[16];
  306.  
  307.     if (!msg_cnt) {
  308.     wprint("No Messages.\n");
  309.     return;
  310.     }
  311.     if (fd) {
  312.     int line;
  313.     Rect *hdr_rect;
  314.  
  315.     if (!msg_menu)
  316.         get_msg_menu();
  317.     (void) sprintf(buf, "Message #%d", message+1);
  318.     /* provide feedback about what message the menu references */
  319.     for (line = 0; line <= n_array[screen-1]; line++)
  320.         if (n_array[line] == message)
  321.         break;
  322.     hdr_rect = (Rect *)window_get(hdr_sw, WIN_RECT);
  323.     box(0, 5 + line * l_height(),
  324.         hdr_rect->r_width, 5 + (line+1) * l_height());
  325.     /* show menu */
  326.     menu_show(msg_menu, can_sw, event, NULL);
  327.     /* remove feedback */
  328.     box(0, 5 + line * l_height(),
  329.         hdr_rect->r_width, 5 + (line+1) * l_height());
  330.     /* if user selected something, figure out what was selected. */
  331.     if (!cur_msg_item)
  332.         return;
  333.     action = (char *) menu_get(cur_msg_item, MENU_CLIENT_DATA);
  334.     cur_msg_item = (Menu_item)NULL;
  335.     } else
  336.     action = (char *) event;
  337.  
  338.     set_isread(message);
  339.     switch ((int) action) {
  340.     case SAVE_MSG : {
  341.         extern Panel_item msg_num_item, save_item;
  342.         (void) panel_set(msg_num_item, PANEL_VALUE,
  343.                     sprintf(buf, "%d", message+1), NULL);
  344.         event_id(event) = MS_LEFT;
  345.         do_file_dir(save_item, 0, event);
  346.         (void) panel_set(msg_num_item, PANEL_VALUE, NO_STRING, NULL);
  347.     }
  348.     when HELP_MSG :
  349.         help(0, "headers", tool_help);
  350.     when PRNT_MSG : case PRE_MSG : case UNDEL_MSG : case DEL_MSG :
  351.         msg_menu_func(action, message);
  352.     when REPL_MSG : {
  353.         extern Panel_item reply_item;
  354.         (void) open_compose();
  355.         /* reply_item shouldn't be here */
  356.         respond_mail(reply_item, message, NO_EVENT);
  357.     }
  358.     otherwise :
  359.         if (current_msg != message) {
  360.         current_msg = message;
  361.         (void) do_hdrs(0, DUBL_NULL, NULL);
  362.         }
  363. #ifdef SUN_3_5
  364.         /* Test for a shortage of file descriptors */
  365.         if (nopenfiles(0) > 3)
  366. #endif /* SUN_3_5 */
  367.         turnon(glob_flags, NEW_FRAME);
  368.         more_prompt = compose_hdr(message);
  369.         display_msg(message, (u_long)0);
  370.     }
  371. }
  372.  
  373. /* msg_menu_func() is a function called to perform message menu actions
  374.  * that are either selected from the popup menu in the header window or
  375.  * from mouse actions that function as accelerators.
  376.  */
  377. static void
  378. msg_menu_func(action, message)
  379. char *action;
  380. {
  381.     int argc;
  382.     register char **argv;
  383.     char buf[32];
  384.  
  385.     wprint("Message #%d ", message+1);
  386.     if (action == UNDEL_MSG || action == DEL_MSG)
  387.     wprint("%sd.\n", sprintf(buf, "%selete",
  388.                 (action == DEL_MSG)? "d": "und"));
  389.     else if (action == PRNT_MSG) {
  390.     wprint("sent to printer.\n");
  391.     (void) strcpy(buf, "lpr");
  392.     } else if (action == PRE_MSG)
  393.     wprint("%sd.\n", strcpy(buf, "preserve"));
  394.     (void) sprintf(&buf[strlen(buf)], " %d", message+1);
  395.  
  396.     if (argv = make_command(buf, (char ***) DUBL_NULL, &argc))
  397.     (void) do_command(argc, argv, msg_list);
  398. }
  399.